import global from '@/views/Global.vue'
import * as echarts from 'echarts'
let analyse = {

    methods: {
        // 坡向
        initViewer() {
            const that = this
            global.viewer.scene.globe.depthTestAgainstTerrain = true;
            global.startAndEndPoints = [],
                global.interNumber = 5000,
                global.points = []
            const handler = new window.Cesium.ScreenSpaceEventHandler(global.viewer.scene.canvas);
            global.viewer.poxiangHandler = handler
            handler.setInputAction(function(movement) {
                global.startAndEndPoints.push(global.viewer.scene.pickPosition(movement.position))
                if (global.startAndEndPoints.length == 1) {
                    global.viewer.entities.removeAll()
                    let poi1 = getPoint(movement)
                    global.points.push(poi1)
                    const dian1 = global.viewer.entities.add({
                        position: Cesium.Cartesian3.fromDegrees(global.points[0].longitude, global.points[0].latitude, global.points[0].altitude),
                        point: {
                            color: Cesium.Color.fromCssColorString('#60cdad'),
                            outlineWidth: 3,
                            outlineColor: Cesium.Color.WHITE,
                            pixelSize: 10
                        }
                    })
                } else if (global.startAndEndPoints.length == 2) {
                    document.getElementById("echarts").style.visibility = "visible";
                    that.isEchartsShow = true;
                    let poi2 = getPoint(movement)
                    global.points.push(poi2)
                    const polilineP = getPointArr([global.points[0].longitude, global.points[0].latitude, global.points[1].longitude, global.points[1].latitude])
                    const dian2 = global.viewer.entities.add({
                        position: Cesium.Cartesian3.fromDegrees(global.points[1].longitude, global.points[1].latitude, global.points[1].altitude),
                        point: {
                            color: Cesium.Color.fromCssColorString('#60cdad'),
                            outlineColor: Cesium.Color.WHITE,
                            outlineWidth: 3,
                            pixelSize: 10
                        },
                    })
                    console.log(global.points, '++');
                    const line = global.viewer.entities.add({
                        polyline: {
                            positions: polilineP,
                            width: 8,
                            material: Cesium.Color.fromCssColorString('#00ff4c'),
                            clampToGround: true,
                            zIndex: 9999,
                            show: true
                        }
                    })
                    console.log(line, '**');
                    var profile = {
                        arrHB: [],
                        arrPoint: [],
                        arrLX: [],
                        ponits: [],
                        distance: 0
                    }
                    for (let i = 0; i < global.startAndEndPoints.length - 1; i++) {
                        var point = equidistantInterpolation(global.startAndEndPoints[i], global.startAndEndPoints[i + 1])
                        profile.arrPoint.push(point)
                    }
                    for (var j = 0; j < profile.arrPoint.length; j++) {
                        for (var m = 0; m < profile.arrPoint[j].length; m++) {
                            profile.ponits.push(profile.arrPoint[j][m])
                        }
                    }
                    profile.arrLX.push(0)
                    for (var k = 1; k < profile.ponits.length - 1; k++) {
                        profile.arrHB.push(profile.ponits[k].hit)
                        var disc = distance(profile.ponits[k - 1], profile.ponits[k])
                        profile.distance = profile.distance + disc
                        profile.arrLX.push(profile.arrLX[k - 1] + disc)
                    }
                    console.log(profile)
                    initChart(profile)
                    global.startAndEndPoints = []
                    global.points = []
                }
            }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

            function equidistantInterpolation(pointA, pointB) {
                // 插值处理
                var tpLength = getArcLength(pointA, pointB)
                    // 插值间距按照输入的插值来进行
                var interpolationNumber = parseInt(tpLength / global.interNumber)
                var pointAToW84 = worldCoordinateToLonAndLat(pointA)
                var pointBToW84 = worldCoordinateToLonAndLat(pointB)
                var lat1 = window.Cesium.Math.toRadians(pointAToW84.lat)
                var lon1 = window.Cesium.Math.toRadians(pointAToW84.lon)
                var lat2 = window.Cesium.Math.toRadians(pointBToW84.lat)
                var lon2 = window.Cesium.Math.toRadians(pointBToW84.lon)
                var spaceList = []
                    // 插值坐标数组
                for (var i = 0; i < interpolationNumber + 1; i++) {
                    var lonRadians = window.Cesium.Math.lerp(lon1, lon2, i / interpolationNumber)
                    var latRadians = window.Cesium.Math.lerp(lat1, lat2, i / interpolationNumber)
                    var lon = window.Cesium.Math.toDegrees(lonRadians)
                    var lat = window.Cesium.Math.toDegrees(latRadians)
                        // 计算插值点坐标
                    var point = {
                        lon: Number(lon),
                        lat: Number(lat)
                    }
                    point = getGeoCoordinate(point.lat, point.lon)
                    point.len = 0
                    spaceList.push(point)
                }
                return spaceList
            }

            function getArcLength(pointA, pointB) {
                var lat1 = pointA.x
                var lon1 = pointA.y
                var lat2 = pointB.x
                var lon2 = pointB.y

                var EARTH_RADIUS = 6378137.0
                var PI = Math.PI

                // 弧度
                function getRad(d) {
                    return d * PI / 180.0
                }

                var f = getRad((lat1 + lat2) / 2)
                var g = getRad((lat1 - lat2) / 2)
                var l = getRad((lon1 - lon2) / 2)

                var sg = Math.sin(g)
                var sl = Math.sin(l)
                var sf = Math.sin(f)

                var s, c, w, r, d, h1, h2
                    // 地球半径
                var a = EARTH_RADIUS
                    // 地球扁率
                var fl = 1 / 298.257

                sg = sg * sg
                sl = sl * sl
                sf = sf * sf

                s = sg * (1 - sl) + (1 - sf) * sl
                c = (1 - sg) * (1 - sl) + sf * sl

                w = Math.atan(Math.sqrt(s / c))
                r = Math.sqrt(s * c) / w
                d = 2 * w * a
                h1 = (3 * r - 1) / 2 / c
                h2 = (3 * r + 1) / 2 / s
                return d * (1 + fl * (h1 * sf * (1 - sg) - h2 * (1 - sf) * sg))
            }

            function worldCoordinateToLonAndLat(cartesian3) {
                const cartographic = window.Cesium.Cartographic.fromCartesian(cartesian3)
                const lat = window.Cesium.Math.toDegrees(cartographic.latitude)
                const lng = window.Cesium.Math.toDegrees(cartographic.longitude)
                const alt = cartographic.height
                return { lon: lng, lat: lat, hit: alt }
            }

            function getGeoCoordinate(lat, lon) {
                var terrainheight = global.viewer.scene.globe.getHeight(window.Cesium.Cartographic.fromDegrees(lon, lat));
                (terrainheight !== undefined) ? terrainheight: 0
                var point = {
                    lon: lon,
                    lat: lat,
                    hit: terrainheight
                }
                return point
            }

            function distance(point1, point2) {
                /** 根据经纬度计算出距离**/
                var strat = window.Cesium.Cartographic.fromDegrees(point1.lon, point1.lat, point1.hit)
                var end = window.Cesium.Cartographic.fromDegrees(point2.lon, point2.lat, point2.hit)
                var geodesic = new window.Cesium.EllipsoidGeodesic()
                geodesic.setEndPoints(strat, end)
                var s = geodesic.surfaceDistance
                    // 返回两点之间的距离
                s = (Math.sqrt(Math.pow(s, 2) + Math.pow(strat.height - end.height, 2))) / 1000
                    // s = Math.abs(strat.height - end.height) / 1000
                return s
            }

            function initChart(e) {
                function strFormat(str) {
                    var strString = String(str)
                    var strs = strString.slice(0, strString.indexOf('.') + 3)
                    return strs
                }
                var t = e.ponits
                var chartData = {
                    dataZoom: [{
                        type: 'inside',
                        throttle: 50
                    }],
                    valueAxis: {
                        position: 'left',
                        axisLine: { // 坐标轴线
                            show: true, // 默认显示，属性show控制显示与否
                            lineStyle: { // 属性lineStyle控制线条样式
                                color: '#48b',
                                width: 2,
                                type: 'solid'
                            }
                        }
                    },
                    grid: {
                        x: 50,
                        y: 40,
                        x2: 80,
                        y2: 40,
                        backgroundColor: 'rgba(0,0,0,0)',
                        borderWidth: 1,
                        borderColor: '#ccc'
                    },
                    tooltip: {
                        trigger: 'axis',
                        formatter: function(e) {
                                // console.log(e, 'kkkkk')
                                var a = ''
                                if (e.length === 0) return a
                                e[0].value
                                var r = t[e[0].dataIndex]
                                    // console.log(r, 'shujuchakan')
                                return a += '所在位置&nbsp;' + strFormat(r.lon) + ',' + strFormat(r.lat) + '</label><br />' + e[0].seriesName + '&nbsp;' + strFormat(r.hit) + "&nbsp;<label style='color:" + e[0].color + ";'>"
                            }
                            /*  */
                    },
                    xAxis: [{
                        name: '距离[km]',
                        // nameLocation: 'left',
                        type: 'category',
                        boundaryGap: false,
                        axisLine: {
                            show: true,
                            symbol: ['none', 'arrow'], // 是否显示轴线箭头
                            symbolSize: [6, 6], // 箭头大小
                            symbolOffset: [0, 7], // 箭头位置
                            lineStyle: {
                                width: 1,
                                type: 'solid'
                            }
                        },
                        axisTick: { // 坐标轴刻度
                            show: true, // 是否显示
                            inside: false, // 是否朝内
                            length: 3, // 长度
                            lineStyle: { // 默认取轴线的样式
                                width: 1,
                                type: 'solid'
                            }
                        },
                        axisLabel: {
                            show: true,
                            interval: 'auto'
                                // formatter:
                        },
                        data: e.arrLX

                    }],
                    yAxis: [{
                        name: '高程值[m]',
                        type: 'value',
                        axisLabel: {
                            rotate: 30,
                            interval: '50'
                        },
                        axisLine: { // 坐标轴 轴线
                            show: true, // 是否显示
                            symbol: ['none', 'arrow'], // 是否显示轴线箭头
                            symbolSize: [6, 6], // 箭头大小
                            symbolOffset: [0, 7], // 箭头位置
                            lineStyle: {
                                width: 1,
                                type: 'solid'
                            }
                        },
                        axisTick: { // 坐标轴刻度
                            show: true, // 是否显示
                            inside: false, // 是否朝内
                            length: 3, // 长度
                            lineStyle: { // 默认取轴线的样式
                                width: 1,
                                type: 'solid'
                            }
                        }

                    }],
                    series: [{
                        name: '高程值',
                        type: 'line',
                        smooth: !0,
                        symbol: 'none',
                        sampling: 'average',
                        zlevel: 1,
                        z: 1,
                        itemStyle: {
                            color: 'rgb(255, 70, 131)'
                        },
                        areaStyle: {
                            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
                                    offset: 0,
                                    color: 'rgb(255, 158, 68)'
                                },
                                {
                                    offset: 1,
                                    color: 'rgb(255, 70, 131)'
                                }
                            ])

                        },
                        data: e.arrHB
                    }]
                }
                echarts.init(document.getElementById("echarts")).setOption(chartData)
            }

            function getPoint(e) {
                let ray = global.viewer.camera.getPickRay(e.position);
                let cartesian = global.viewer.scene.globe.pick(ray, global.viewer.scene);
                let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
                let lng = Cesium.Math.toDegrees(cartographic.longitude); // 经度
                let lat = Cesium.Math.toDegrees(cartographic.latitude); // 纬度
                let alt = cartographic.height; // 高度
                let coordinate = {
                    longitude: Number(lng.toFixed(6)),
                    latitude: Number(lat.toFixed(6)),
                    altitude: Number(alt.toFixed(2))
                };
                return coordinate;
            }

            function getPointArr(points) {
                let pointArr = new Cesium.CallbackProperty(() => {
                    return new Cesium.Cartesian3.fromDegreesArray(points)
                }, false)
                return pointArr
            }


        },
        // 挖方
        excavate() {
            const viewer = global.viewer
            const excavateHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
            excavateHandler.setInputAction(function(e) {
                let polylineArr = []
                let ray = viewer.camera.getPickRay(e.position)
                let cartesian = viewer.scene.globe.pick(ray, viewer.scene)
                global.excavatePositions.push(cartesian)
                let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
                let lon = Cesium.Math.toDegrees(cartographic.longitude); // 经度
                let lat = Cesium.Math.toDegrees(cartographic.latitude); // 纬度
                let alt = cartographic.height; // 高度
                polylineArr.push(lon, lat)
                let point = viewer.entities.add({
                    position: Cesium.Cartesian3.fromDegrees(lon, lat, alt),
                    point: {
                        color: Cesium.Color.fromCssColorString('#60cdad'),
                        pixelSize: 15,
                        outlineColor: Cesium.Color.WHITE,
                        outlineWidth: 3,
                        clampToGroundL: true,
                        disableDepthTestDistance: 2000
                    },
                })
            }, Cesium.ScreenSpaceEventType.LEFT_CLICK)

            // 右键开始分析
            excavateHandler.setInputAction(function(e) {
                let polygon = viewer.entities.add({
                    hierarchy: new Cesium.PolygonHierarchy(global.excavatePositions),
                    material: Cesium.Color.YELLOW.withAlpha(0.6),
                    classificationType: Cesium.ClassificationType.BOTH
                })
                excavateHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
                excavateHandler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK)
                const result = new CutAndFillResult();
                //声明屏幕坐标数组
                const windowPositions = [];
                //先遍历一下多边形节点，获取最低高程点，作为基准高程
                //同时将Cartesian3转为屏幕坐标，存放在数组中
                global.excavatePositions.forEach(element => {
                        const cartographic = Cesium.Cartographic.fromCartesian(element);
                        global.baseHeight = Math.min(cartographic.height, global.baseHeight);
                        windowPositions.push(Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene, element));
                    })
                    //构建泰森多边形的过程
                const bounds = getBounds(windowPositions);
                const points = turf.randomPoint(50, { bbox: [bounds[0], bounds[1], bounds[2], bounds[3]] });
                const mainPoly = Cartesian2turfPolygon(windowPositions);
                const voronoiPolygons = turf.voronoi(points, { bbox: [bounds[0], bounds[1], bounds[2], bounds[3]] });

                //遍历泰森多边形
                voronoiPolygons.features.forEach(element => {
                    const intersectPoints = intersect(mainPoly, element.geometry);
                    if (intersectPoints.length > 0) {
                        //计算每个多边形的面积和高度
                        const cubeInfo = computeCubeInfo(intersectPoints);
                        //低于基准面，填方
                        if (global.baseHeight > cubeInfo.avgHeight) {
                            result.fillVolume += (global.baseHeight - cubeInfo.avgHeight) * result.baseArea;
                        } else { //高于基准面，挖方
                            result.cutVolume += (cubeInfo.avgHeight - global.baseHeight) * result.baseArea;
                        }
                        result.maxHeight = Math.max(result.maxHeight, cubeInfo.maxHeight);
                        result.minHeight = Math.min(result.minHeight, cubeInfo.minHeight);
                        result.baseArea += cubeInfo.baseArea;
                    }
                });
                return result;

                function computeCubeInfo(positions) {
                    let worldPositions = [];
                    let minHeight = Number.MAX_VALUE;
                    let maxHeight = Number.MIN_VALUE;
                    let sumHeight = 0.0;
                    positions.forEach(element => {
                        const worldPostion = pickCartesian(viewer, element).cartesian;
                        const cartographic = Cesium.Cartographic.fromCartesian(worldPostion);
                        worldPositions.push(cartographic);
                        minHeight = Math.min(minHeight, cartographic.height);
                        maxHeight = Math.max(maxHeight, cartographic.height);
                        sumHeight += cartographic.height;
                    });
                    const avgHeight = sumHeight / positions.length;
                    const result = new CubeInfo();
                    result.minHeight = minHeight;
                    result.maxHeight = maxHeight;
                    result.avgHeight = avgHeight;
                    result.baseArea = getAreaFromCartograohics(worldPositions);
                    return result;
                }

                function getBounds(points) {
                    let bounds = [];
                    let left = Number.MAX_VALUE;
                    let right = Number.MIN_VALUE;
                    let top = Number.MAX_VALUE;
                    let bottom = Number.MIN_VALUE;
                    points.forEach(element => {
                        left = Math.min(left, element.x);
                        right = Math.max(right, element.x);
                        top = Math.min(top, element.y);
                        bottom = Math.max(bottom, element.y);
                    });
                    bounds.push(left);
                    bounds.push(top);
                    bounds.push(right);
                    bounds.push(bottom);
                    return bounds;
                }

                function Cartesian2turfPolygon(positions) {
                    var coordinates = [
                        []
                    ];
                    positions.forEach(element => {
                        coordinates[0].push([element.x, element.y]);
                    });
                    coordinates[0].push([positions[0].x, positions[0].y]);
                    const polygon = turf.polygon(coordinates);
                    return polygon.geometry;
                }

                function turfPloygon2CartesianArr(geometry) {
                    const positionArr = [];
                    geometry.coordinates.forEach((pointArr) => {
                        pointArr.forEach(point => {
                            positionArr.push(new Cesium.Cartesian2(point[0], point[1]));
                        });
                    });
                    positionArr.push(new Cesium.Cartesian2(geometry.coordinates[0][0][0], geometry.coordinates[0][0][1]));
                    return positionArr;
                }


                function intersect(poly1, poly2) {
                    var intersection = turf.intersect(poly1, poly2);
                    if (intersection !== undefined) {
                        return turfPloygon2CartesianArr(intersection);
                    } else {
                        return [];
                    }
                }

                function getAreaFromCartograohics(positions) {
                    const x = [0];
                    const y = [0];
                    const geodesic = new Cesium.EllipsoidGeodesic();
                    const radiansPerDegree = Math.PI / 180.0; //角度转化为弧度(rad)
                    //数组x,y分别按顺序存储各点的横、纵坐标值
                    for (let i = 0; i < positions.length - 1; i++) {
                        const p1 = positions[i];
                        const p2 = positions[i + 1];
                        geodesic.setEndPoints(p1, p2);
                        //   const s = Math.sqrt(Math.pow(geodesic.surfaceDistance, 2) +
                        //     Math.pow(p2.height - p1.height, 2));
                        const s = Math.sqrt(Math.pow(geodesic.surfaceDistance, 2));
                        // console.log(s, p2.y - p1.y, p2.x - p1.x)
                        const lat1 = p2.latitude * radiansPerDegree;
                        const lon1 = p2.longitude * radiansPerDegree;
                        const lat2 = p1.latitude * radiansPerDegree;
                        const lon2 = p1.longitude * radiansPerDegree;
                        let angle = -Math.atan2(
                            Math.sin(lon1 - lon2) * Math.cos(lat2),
                            Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon1 - lon2)
                        );
                        if (angle < 0) {
                            angle += Math.PI * 2.0;
                        }
                        console.log('角度：' + (angle * 180) / Math.PI);

                        y.push(Math.sin(angle) * s + y[i]);
                        x.push(Math.cos(angle) * s + x[i]);
                    }

                    let sum = 0;
                    for (let i = 0; i < x.length - 1; i++) {
                        sum += x[i] * y[i + 1] - x[i + 1] * y[i];
                    }
                    // console.log(x, y)

                    return Math.abs(sum + x[x.length - 1] * y[0] - x[0] * y[y.length - 1]) / 2;
                }



                function pickCartesian(viewer, windowPosition) {
                    //根据窗口坐标，从场景的深度缓冲区中拾取相应的位置，返回笛卡尔坐标。
                    const cartesianModel = viewer.scene.pickPosition(windowPosition);
                    //场景相机向指定的鼠标位置（屏幕坐标）发射射线
                    const ray = viewer.camera.getPickRay(windowPosition);
                    //获取射线与三维球相交的点（即该鼠标位置对应的三维球坐标点，因为模型不属于球面的物体，所以无法捕捉模型表面）
                    const cartesianTerrain = viewer.scene.globe.pick(ray, viewer.scene);

                    const result = new PickResult();
                    if (typeof(cartesianModel) !== 'undefined' && typeof(cartesianTerrain) !== 'undefined') {
                        result.cartesian = cartesianModel || cartesianTerrain;
                        result.CartesianModel = cartesianModel;
                        result.cartesianTerrain = cartesianTerrain;
                        result.windowCoordinates = windowPosition.clone();
                        //坐标不一致，证明是模型，采用绝对高度。否则是地形，用贴地模式。
                        result.altitudeMode = cartesianModel.z.toFixed(0) !== cartesianTerrain.z.toFixed(0) ? Cesium.HeightReference.NONE : Cesium.HeightReference.CLAMP_TO_GROUND;
                    }
                    return result;
                }

            }, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
            class CutAndFillResult {
                minHeight = Number.MAX_VALUE;
                maxHeight = Number.MIN_VALUE;
                cutVolume = 0.0;
                fillVolume = 0.0;
                baseArea = 0.0;
            }
            class CubeInfo {
                minHeight = Number.MAX_VALUE;
                maxHeight = Number.MIN_VALUE;
                avgHeight = 0.0;
                baseArea = 0.0;
            }

        }
    },
}
export default analyse